﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using Common.Net.DesignByContract;
using Common.Net.Utilities;

namespace ClearUnit.TestRunners.Results
{
    public abstract class TypeRunResult : TestRunResult
    {
        readonly Type _type;

        public Type Type
        {
            get { return _type; }
        }

        readonly IList<MethodRunResult> _methods;

        public IList<MethodRunResult> Methods
        {
            get { return _methods; }
        }

        public TypeRunResult(Type type, IList<MethodRunResult> methods)
        {
            RequireArg.NotNull(() => type);

            _type = type;
            _methods = methods.ToReadOnly();
        }

        public class Skipped : TypeRunResult
        {
            public Skipped(Type type, IList<MethodRunResult> methods)
                : base(type, methods)
            {
            }

            public override string ShortDescription
            {
                get { return string.Format("Type {0} skipped", Type.Name); }
            }
        }

        public class Run : TypeRunResult
        {
            public int PassedCount
            {
                get { return Methods.Count(m => m is MethodRunResult.Run.Passed); }
            }

            public int SkippedCount
            {
                get { return Methods.Count(m => m is MethodRunResult.Skipped); }
            }

            public int FailedCount
            {
                get { return Methods.Count(m => m is MethodRunResult.Run.Failed); }
            }

            public IEnumerable<MethodRunResult.Run> MethodsRun
            {
                get { return Methods.OfType<MethodRunResult.Run>(); }
            }

            public TimeSpan TotalLength
            {
                get { return MethodsRun.Sum(m => m.Length); }
            }

            public Run(Type type, IList<MethodRunResult> methods)
                :base(type, methods)
            {
            }

            public override string ShortDescription
            {
                get { return string.Format("Type {0} tests: {1} passed, {2} failed, {3} skipped (took {4})", _type.Name, PassedCount, FailedCount, SkippedCount, TotalLength.Format()); }
            }
        }
    }

}